<!--
 * @Description: 列表组件
 * @Author: HuiSir<https://gitee.com/huisir001>
 * @Date: 2025-09-27 11:48:31
 * @LastEditTime: 2025-09-28 11:59:34
-->
<template>
  <div
    class="fy-list"
    :class="`fy-list--${size} ${border ? 'fy-list--border' : ''}`"
    :style="{
      '--item-space': rowSpace + 'px',
      '--item-bg-color': rowBgColor,
      '--item-act-bg-color': highlightBgColor,
      '--item-act-color': highlightColor,
      '--item-radius': rowRadius + 'px',
      '--item-cursor': useCursorPointer ? 'pointer' : 'default',
    }"
  >
    <div
      v-for="(item, index) in list"
      :key="index"
      class="fy-list-item"
      :class="{
        active: index === activeItemIndex && !item.disabled,
        disabled: item.disabled,
      }"
      @click="activeItemIndex = index"
    >
      <slot v-if="$slots.listItem" name="listItem" v-bind="item" />
      <template v-else>
        <div class="left">
          <fy-icon
            v-if="item.icon || icon"
            :name="item.icon || icon"
            :size="iconSize"
            :color="
              index === activeItemIndex
                ? highlightColor
                : 'var(--el-text-color-primary)'
            "
          />
          <div class="content">
            <div v-if="$slots.title" class="slot-title">
              <slot name="title" v-bind="item" />
            </div>
            <div v-else-if="item.title" class="title">{{ item.title }}</div>
            <div v-if="$slots.desc" class="slot-desc">
              <slot name="desc" v-bind="item" />
            </div>
            <div v-else-if="item.desc" class="desc">{{ item.desc }}</div>
          </div>
        </div>
        <div
          v-if="
            $slots.actions ||
            item.actions ||
            actions ||
            item.rightIcon ||
            rightIcon
          "
          class="right"
        >
          <div v-if="$slots.actions" class="slot-action">
            <slot name="actions" v-bind="item" />
          </div>
          <div v-else-if="item.actions || actions" class="action">
            <el-button
              v-for="action in item.actions || actions"
              :key="action.name"
              :type="action.type || 'primary'"
              link
              size="small"
              @click.stop="handleActionTap(index, item)"
            >
              <fy-icon
                v-if="action.icon"
                :name="action.icon"
                size="13"
                :color="index === activeItemIndex ? highlightColor : 'inherit'"
              />
              {{ action.title || action.name }}
            </el-button>
          </div>
          <fy-icon
            v-if="item.rightIcon || rightIcon"
            :name="item.rightIcon || rightIcon"
            :size="rightIconSize"
          />
        </div>
      </template>
    </div>
    <!-- 完善分页：加载更多按钮 -->
    <div v-if="showLoadMore" class="load-more">
      <el-button
        type="primary"
        link
        @click="emit('loadMore')"
        :loading="loadMoreLoading"
      >
        <fy-icon
          v-if="!loadMoreLoading"
          name="DArrowRight"
          size="14"
          width="20px"
        />
        加载更多
      </el-button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { watch } from "vue";
import { ListProps, ListItem } from "../types";

const props = withDefaults(defineProps<ListProps>(), {
  icon: false,
  border: false,
  rightIcon: false,
  size: "medium",
  iconSize: 20,
  rightIconSize: 14,
  rowSpace: 0,
  rowRadius: 4,
  rowBgColor: "transparent",
  highlightBgColor: "transparent",
  highlightColor: "inherit",
  useCursorPointer: false,
  loadMoreLoading: false,
  showLoadMore: false,
  list: () => [],
  actions: () => [],
});

const activeItemIndex = defineModel("activeItemIndex", {
  type: Number,
  default: 0,
});

/**
 * 监听列表变化，当选中项为disabled禁用状态时，自动更改选中项为列表的第一项非禁用项
 */
watch(
  () => props.list,
  (newVal: ListItem[]) => {
    if (newVal.length === 0) {
      activeItemIndex.value = 0;
      return;
    }
    const activeItem = newVal[activeItemIndex.value];
    if (activeItem.disabled) {
      activeItemIndex.value = newVal.findIndex((item) => !item.disabled);
    }
  },
  {
    immediate: true,
    once: true,
  }
);

const emit = defineEmits(["actionClick", "loadMore"]);

const handleActionTap = (index: number, item: ListItem) => {
  emit("actionClick", index, item);
};
</script>

<style scoped lang="scss">
.fy-list {
  .fy-list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    line-height: 1.6;
    font-size: var(--el-font-size-base);
    background-color: var(--item-bg-color);
    border-radius: var(--item-radius);
    cursor: var(--item-cursor);
    transition: all 0.2s ease-in-out;
    & + .fy-list-item {
      margin-top: var(--item-space);
    }
    &.active {
      background-color: var(--item-act-bg-color);
      * {
        color: var(--item-act-color) !important;
      }
    }
    &.disabled {
      cursor: not-allowed;
      pointer-events: none;
      opacity: 0.5;
    }
    .left,
    .right {
      display: flex;
    }
    .left {
      align-items: flex-start;
      justify-content: flex-start;
      .content {
        .title {
          color: var(--el-text-color-primary);
          font-weight: 500;
        }
        .desc {
          color: var(--el-text-color-regular);
        }
        .title,
        .desc,
        .slot-title,
        .slot-desc {
          word-break: break-all;
        }
      }
    }
    .right {
      justify-content: flex-end;
      align-items: center;
    }
  }
  .load-more {
    margin: 20px 0 10px auto;
    text-align: center;
    :deep(.el-button) {
      margin-left: -15px;
      .fy-icon {
        transform: rotate(90deg);
      }
    }
  }
}
.fy-list--small {
  .fy-list-item {
    padding: 6px 8px;
  }
}
.fy-list--large {
  .fy-list-item {
    padding: 12px 16px;
  }
}
.fy-list--border {
  .fy-list-item {
    border-bottom: var(--el-border);
  }
}
</style>
